package source;

import java.util.Random;

public class Drone extends Thread {
	private final int playerID;
	private final SupplyDepot depot;
	private final Map map;

	// starea in care se afla drona
	private volatile int state = 0;

	private Player ownerPlayer = null;

	public Drone(int playerID, SupplyDepot depot, Player player) {
		this.ownerPlayer = player;
		this.playerID = playerID;
		this.depot = depot;
		this.map = Map.getInstance();
		this.state = 0;
	}

	// metode apelate de player pe drona pt a schimba starea
	// sunt sincronizate pt a evita citirea gresita a starii de catre drona
	public synchronized void mineGold() {
		if (state == 0)
			notify();
		state = 1;
	}

	public synchronized void mineStone() {
		if (state == 0)
			notify();
		state = 2;
	}

	public synchronized void cutWood() {
		if (state == 0)
			notify();
		state = 3;
	}

	public synchronized void gatherFood() {
		if (state == 0)
			notify();
		state = 4;
	}

	public synchronized void buildHouse() {
		if (state == 0)
			notify();
		state = 5;
	}

	public synchronized void buildStatue() {
		if (state == 0)
			notify();
		state = 6;
	}

	public synchronized void buildDrone() {
		if (state == 0)
			notify();
		state = 7;
	}

	// metoda ce simuleaza o intarziere pt minare
	// este apelata din harta
	public void extractSomething() {
		for (int i = 0; i < 10000; i++)
			;
	}

	// metoda ce spune daca drona este in idle
	public synchronized boolean isIdle() {
		return state == 0;
	}

	@Override
	public void run() {
		while (true) {
			// sincronizare pe lockState pt ca drona sa citeasca o valoare
			// corecta a starii curente
			// test pentru final de joc
			if (map.isMapFull()) {
				ownerPlayer.removeDroneFromMainVector(this);
				break;
			}

			switch (state) {
			case 0:
				synchronized (this) {
					while (state == 0) {
						try {
							this.wait();
						} catch (InterruptedException e) {
							Thread.currentThread().interrupt();
							e.printStackTrace();
						}
					}
				}
				break;
			case 1:
				try {
					depot.addGold(map.mineGold(this));
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.currentThread().interrupt();
				}
				break;
			case 2:
				try {
					depot.addStone(map.mineStone(this));
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.currentThread().interrupt();
				}
				break;
			case 3:
				try {
					depot.addWood(map.cutWood(this));
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.currentThread().interrupt();
				}
				break;
			case 4:
				try {
					depot.addFood(map.gatherFood(this));
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.currentThread().interrupt();
				}
				break;
			// daca comanda reprezinta construire se alege random o pozitie
			// pe harta
			case 5:

				if (depot.getMaterialsForConstruction(15, 15, 15)) {
					Random random1 = new Random();

					int pozx1 = random1.nextInt(Map.n);
					int pozy1 = random1.nextInt(Map.n);

					// in result1 se salveaza ce returneaza buildHouse()
					// pentru a stii in ce stare se afla pozitia aleasa
					// 1=libera sau in construire de o drona prieten, 2=a
					// celuilalt player, 3=construita
					int result1 = map.buildHouse(this.playerID,
							this.hashCode(), pozx1, pozy1);

					while (!(result1 == 2 || result1 == 3)) {
						result1 = map.buildHouse(this.playerID,
								this.hashCode(), pozx1, pozy1);

						if (result1 == 3)
							System.out.println("Drone_" + playerID
									+ " has built a house at " + pozx1 + " "
									+ pozy1);

						if (result1 == 2)
							System.out.println("Drone_" + playerID
									+ " could not build a house at " + pozx1
									+ " " + pozy1);
					}
				}
				state = 0;
				ownerPlayer.addToIdleList(this);
				break;
			case 6:
				if (depot.getMaterialsForConstruction(25, 25, 25)) {
					// daca comanda reprezinta construire se alege random o
					// pozitie pe harta
					Random random2 = new Random();

					int pozx2 = random2.nextInt(Map.n);
					int pozy2 = random2.nextInt(Map.n);

					// in result1 se salveaza ce returneaza buildStatue()
					// pentru
					// a stii in ce stare se afla pozitia aleasa
					// 1=libera sau in construire de o drona prieten, 2=a
					// celuilalt player, 3=construita
					int result2 = map.buildStatue(this.playerID,
							this.hashCode(), pozx2, pozy2);

					while (!(result2 == 2 || result2 == 3)) {

						result2 = map.buildStatue(this.playerID,
								this.hashCode(), pozx2, pozy2);

						if (result2 == 3)
							System.out.println("Drone_" + playerID
									+ " has built a statue at " + pozx2 + " "
									+ pozy2);

						if (result2 == 2)
							System.out.println("Drone_" + playerID
									+ " could not build a statue at " + pozx2
									+ " " + pozy2);
					}
				}
				state = 0;
				ownerPlayer.addToIdleList(this);
				break;
			// comanda de construire drona
			case 7:
				if (depot.getMaterialsForDrone(100, 100)) {
					ownerPlayer.receiveNewDrone(new Drone(playerID, depot,
							ownerPlayer));
				}
				state = 0;
				ownerPlayer.addToIdleList(this);
				break;
			}
		}
	}
}
